package libra;

import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Service;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;

@Service
public class TestService {
	/**
	 * 测试在AOP环境下使用@SentinelResource注解
	 * 	value：
	 * 		资源名称，必需项（不能为空）
	 * 	entryType：
	 * 		entry 类型，可选项（默认为 EntryType.OUT）
	 * 	blockHandler / blockHandlerClass: 
	 * 		blockHandler对应处理BlockException的函数名称，可选项。
	 * 		blockHandler函数访问范围需要是public，返回类型需要与原方法相匹配，参数类型需要和原方法相匹配并且最后加一个额外的参数，类型为BlockException。
	 * 		blockHandler函数默认需要和原方法在同一个类中。
	 * 		若希望使用其他类的函数，则可以指定blockHandlerClass为对应的类的Class对象，注意对应的函数必需为static函数，否则无法解析。
	 * 	fallback / fallbackClass：
	 * 		fallback函数名称，可选项，用于在抛出异常的时候提供fallback处理逻辑。
	 * 		fallback函数可以针对所有类型的异常（除了 exceptionsToIgnore 里面排除掉的异常类型）进行处理。
	 * 		fallback 函数签名和位置要求：
	 * 			返回值类型必须与原函数返回值类型一致；
	 * 			方法参数列表需要和原函数一致，或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
	 * 			fallback函数默认需要和原方法在同一个类中。
	 * 			若希望使用其他类的函数，则可以指定fallbackClass为对应的类的Class对象，注意对应的函数必需为static函数，否则无法解析。
	 * 	defaultFallback（since 1.6.0）：
	 * 		默认的fallback函数名称，可选项，通常用于通用的fallback逻辑（即可以用于很多服务或方法）。
	 * 		默认fallback函数可以针对所有类型的异常（除了 exceptionsToIgnore 里面排除掉的异常类型）进行处理。
	 * 		若同时配置了fallback和defaultFallback，则只有fallback会生效。
	 * 		defaultFallback 函数签名要求：
	 * 			返回值类型必须与原函数返回值类型一致；
	 * 			方法参数列表需要为空，或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
	 * 			defaultFallback函数默认需要和原方法在同一个类中。
	 * 			若希望使用其他类的函数，则可以指定fallbackClass为对应的类的Class对象，注意对应的函数必需为static函数，否则无法解析。
	 * 	exceptionsToIgnore（since 1.6.0）：
	 * 		用于指定哪些异常被排除掉，不会计入异常统计中，也不会进入fallback逻辑中，而是会原样抛出。
	 * 
	 * 若blockHandler和fallback都进行了配置，则被限流降级而抛出BlockException时只会进入blockHandler处理逻辑。
	 * 若未配置blockHandler、fallback和defaultFallback，则被限流降级时会将BlockException直接抛出。
	 * 若方法本身未定义throws BlockException则会被JVM包装一层UndeclaredThrowableException。
	 */
	@SentinelResource( value = "normalExec", blockHandler = "blockExec", fallback = "fallbackExec" )
	public Object normalExec( String resoucerName, int i, HttpServletResponse resp ) throws Exception {
		System.out.println(resoucerName + "执行正常...");
		if( i % 7 == 0 ) {
			int j = 1/0;
		}
		return resoucerName + "执行正常...";
	}
	// blockExec函数，原方法调用被限流/降级/系统保护的时候调用
	public Object blockExec(String resoucerName, int i, HttpServletResponse resp, BlockException ex) throws Exception {
		resp.setStatus(439);
		// 资源访问阻止，被限流或被降级
		System.err.println( resoucerName + "限流异常...i:" + i + "...Ex:" + ex.getClass().getName() );
		return resoucerName + "限流异常...i:" + i + "...Ex:" + ex.getClass().getName();
	}
	// fallbackExec函数，原方法抛出异常的时候提供fallback处理逻辑
	public Object fallbackExec(String resoucerName, int i, HttpServletResponse resp, Throwable throwable) throws Exception {
		resp.setStatus(500);
		// 资源访问阻止，被限流或被降级
		System.err.println( resoucerName + "执行异常...i:" + i + "...Throwable:" + throwable.getClass().getName() );
		return resoucerName + "执行异常...i:" + i + "...Throwable:" + throwable.getClass().getName();
	}
}
